package com.github.data_manage.config

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer
import jakarta.annotation.PreDestroy
import okhttp3.Dispatcher
import okhttp3.OkHttpClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import java.time.Duration
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors


/**
 *@author CHN
 *@since 2024-08-08 21:08
 */
@Configuration
class BeanConfig {

    companion object {
        val objectMapper: ObjectMapper = let {
            val objectMapper = ObjectMapper()
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
            val javaTimeModule = JavaTimeModule()
            javaTimeModule.addSerializer(
                LocalDateTime::class.java, LocalDateTimeSerializer(
                    DateTimeFormatter.ofPattern(
                        "yyyy-MM-dd HH:mm:ss"
                    )
                )
            )
            javaTimeModule.addDeserializer(
                LocalDateTime::class.java, LocalDateTimeDeserializer(
                    DateTimeFormatter.ofPattern(
                        "yyyy-MM-dd HH:mm:ss"
                    )
                )
            )
            javaTimeModule.addSerializer(
                LocalDate::class.java,
                LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
            )
            javaTimeModule.addDeserializer(
                LocalDate::class.java, LocalDateDeserializer(
                    DateTimeFormatter.ofPattern(
                        "yyyy-MM-dd"
                    )
                )
            )
            javaTimeModule.addSerializer(
                LocalTime::class.java,
                LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss"))
            )
            javaTimeModule.addDeserializer(
                LocalTime::class.java, LocalTimeDeserializer(
                    DateTimeFormatter.ofPattern(
                        "HH:mm:ss"
                    )
                )
            )
            objectMapper.registerModule(javaTimeModule)
            objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
//            objectMapper.factory
//                .setStreamReadConstraints(StreamReadConstraints.builder()
//                    .maxStringLength(Int.MAX_VALUE)
//                    .maxNumberLength(Int.MAX_VALUE).build());
            return@let objectMapper
        }

        val okHttpTaskExecutor: ExecutorService = Executors.newVirtualThreadPerTaskExecutor()
    }

    @Bean
    @Primary
    fun objectMapper(): ObjectMapper = objectMapper

    @Bean
    fun okHttpTaskExecutor(): ExecutorService = okHttpTaskExecutor

    @PreDestroy
    fun preDestroy() {
        okHttpTaskExecutor.shutdown()
    }

    @Bean
    @Primary
    fun okHttpClient(okHttpTaskExecutor: ExecutorService): OkHttpClient {
        val dispatcher = Dispatcher(okHttpTaskExecutor)
        return OkHttpClient.Builder()
            .dispatcher(dispatcher)
            .readTimeout(Duration.ofSeconds(0))
            .build()
    }

}